package cn.hwadee.muying.recommend.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * @创建人 skiner
 * @创建时间 2018/8/13
 * @描述 字符串余弦距离计算，参考https://blog.csdn.net/qq_31417669/article/details/78958898
 */
public class ScoreCos {

    /**
     * 不分词 纯字符串计算
     * @param text1
     * @param text2
     * @return
     */
    public static double similarScoreCos(String text1, String text2){
        if(text1 == null || text2 == null){
            //只要有一个文本为null，规定相似度分值为0，表示完全不相等
            return 0.0;
        }else if("".equals(text1)&&"".equals(text2)) return 1.0;
        Set<Integer> ASII=new TreeSet<>();
        Map<Integer, Integer> text1Map=new HashMap<>();
        Map<Integer, Integer> text2Map=new HashMap<>();
        for(int i=0;i<text1.length();i++){
            Integer temp1=new Integer(text1.charAt(i));
            if(text1Map.get(temp1)==null) text1Map.put(temp1,1);
            else text1Map.put(temp1,text1Map.get(temp1)+1);
            ASII.add(temp1);
        }
        for(int j=0;j<text2.length();j++){
            Integer temp2=new Integer(text2.charAt(j));
            if(text2Map.get(temp2)==null) text2Map.put(temp2,1);
            else text2Map.put(temp2,text2Map.get(temp2)+1);
            ASII.add(temp2);
        }
        double xy=0.0;
        double x=0.0;
        double y=0.0;
        //计算
        for (Integer it : ASII) {
            Integer t1=text1Map.get(it)==null?0:text1Map.get(it);
            Integer t2=text2Map.get(it)==null?0:text2Map.get(it);
            xy+=t1*t2;
            x+=Math.pow(t1, 2);
            y+=Math.pow(t2, 2);
        }
        if(x==0.0||y==0.0) return 0.0;
        return xy/Math.sqrt(x*y);
    }

    /**
     * 使用分词
     * text1，text2为已分词字符串 余弦相似度匹配度
     * @param text1 已分词字符串 eg:这只 皮靴 号码 大了
     * @param text2 已分词字符串  eg:这只 皮靴 号码 小了
     * @return
     */
    public static double similarScoreCosWord(String text1, String text2){
        if(text1 == null || text2 == null)
            return 0.0;
        else if("".equals(text1)&&"".equals(text2)) return 1.0;
        Set<String> word = new TreeSet<>();
        String[] text1Array = text1.split(" ");
        String[] text2Array = text2.split(" ");
        Map<String, Integer> text1Map = new HashMap<>();
        Map<String, Integer> text2Map = new HashMap<>();
        for(int i=0;i<text1Array.length;i++){
            if(text1Map.get(text1Array[i])==null) text1Map.put(text1Array[i],1);
            else text1Map.put(text1Array[i],text1Map.get(text1Array[i])+1);
            word.add(text1Array[i]);
        }
        for(int j=0;j<text2Array.length;j++){
            if(text2Map.get(text2Array[j]) == null) text2Map.put(text2Array[j],1);
            else text2Map.put(text2Array[j],text2Map.get(text2Array[j])+1);
            word.add(text2Array[j]);
        }
        double xy = 0.0;
        double x = 0.0;
        double y = 0.0;
        //计算
        for (String it : word) {
            Integer t1 = text1Map.get(it)==null?0:text1Map.get(it);
            Integer t2 = text2Map.get(it)==null?0:text2Map.get(it);
            xy+=t1*t2;
            x+=Math.pow(t1, 2);
            y+=Math.pow(t2, 2);
        }
        if(x==0.0||y==0.0) return 0.0;
        return xy/Math.sqrt(x*y);
    }
    /**
     * 相同返回1，不同返回0
     * @param o1
     * @param o2
     * @return
     */
    public static double equal(Object o1,Object o2) {
        return (o1!=null && o2!=null)&&o1.equals(o2)?1:0;
    }

    /**
     * 值约接近，返回值越接近1
     * 算法为 1-（大-小）/大
     * @param o1
     * @param o2
     * @return
     */
    public static double similarByNumber(int o1, int o2, int max) {
        return 1-Math.abs(o1-o2)/max;
    }
}
